//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using OpenLS.Spreadsheet.Expressions;
using OpenLS.Spreadsheet.Parsing;

namespace OpenLS.Spreadsheet.UI.Internals
{
    abstract class FormulaDimensionsReference<T, TOther> : FormulaReference where T : Dimension where TOther: Dimension
    {
        internal FormulaDimensionsReference(Token t, FullRangeReference<T, TOther> rangeReference, Formula owner) : base(t, owner)
        {
            RangeReference = rangeReference; 
        }
        internal FormulaDimensionsReference(Token t, DimensionReference<T, TOther> dimensionReference, Formula owner) : base(t, owner)
        {
            _dimensionReference = dimensionReference;
           /* if (typeof (T) == typeof (Row))
                RangeReference = new FullRowRangeReference(dimensionReference, dimensionReference);
            else
            {
                RangeReference = new FullColumnRangeReference(dimensionReference, dimensionReference);
                
            }*/

        }

        private DimensionReference<T, TOther> _dimensionReference;
        private FullRangeReference<T, TOther> _rangeReference;

        internal override string Text
        {
            get
            {
                if (RangeReference != null)

                return RangeReference.Label;
                return _dimensionReference.Label;
            }
        }

        public override Worksheet Worksheet
        {
            get { if (RangeReference != null) return RangeReference.Range.Worksheet;
                return _dimensionReference.Worksheet;
            }
        }

        protected override Cell TopLeft
        {
            get { 
                if (RangeReference != null)
                return RangeReference.Range.TopLeftCell;
                return Worksheet[AsRangeAddress().TopLeft];
                
            }
        }

        protected override string Label
        {
            get
            {
                return RangeReference.Label;
            
            }
        }

        public override int RowSpan
        {
            get { return AsRangeAddress().RowSpan; }
        }

        public override int ColumnSpan
        {
            get { return AsRangeAddress().ColumnSpan; }
        }

        public override bool IsFullRow
        {
            get { return AsRangeAddress().IsFullRow; }
        }

        public override bool IsFullColumn
        {
            get { return AsRangeAddress().IsFullColumn; }
        }


        public FullRangeReference<T, TOther> RangeReference
        {
            get { return _rangeReference; }
            set
            {
                Contract.Assert(value != null);
                _rangeReference = value; NotifyChanged();}
        }

        public DimensionReference<T, TOther> DimensionReference
        {
            get { return _dimensionReference; }
            set {
                Contract.Assert(value != null); _dimensionReference = value;
            }
        }


        public void SetDimensionReference(ColumnReference cr)
        {
            throw new NotImplementedException();
        }

        internal override RangeAddress AsRangeAddress()
        {
            if (RangeReference != null)
            return RangeReference.Range.Address;
            Dimension d = _dimensionReference.Anchor;
            if (d is Row)
                return new RangeAddress(new CellAddress(d.Index, 0),new CellAddress(d.Index, Worksheet.MaxColumnIndex) );
            return new RangeAddress(new CellAddress(0, d.Index),new CellAddress(Worksheet.MaxRowIndex, d.Index) );
        }

        protected static CellRelativeAddress GetRelativeAddress(NavigationDirection navigationDirection)
        {
            switch (navigationDirection)
            {
                case NavigationDirection.Down:return new CellRelativeAddress(1, 0);
                case NavigationDirection.Left:return new CellRelativeAddress(0, -1);
                case NavigationDirection.Right:return new CellRelativeAddress(0, 1);
                case NavigationDirection.Up:return new CellRelativeAddress(-1, 0);
                default: throw new NotSupportedException();
            }
        }

        internal override sealed void Move(CellRelativeAddress address)
        {

            RangeReference = (FullRangeReference<T, TOther>)RangeReference.Offset(address);
            this.DimensionReference = DimensionReference.OffsetDim(address);
            NotifyChanged();
        }
    }
}
